package javafoundation.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @ClassName V_03_实现Callable接口
 * @Description TODO
 * @Author dzf
 * @Date 2023/3/2 10:28
 * @Version 1.0
 */
public class V_03_实现Callable接口 {
    //前面我们介绍的两种创建线程的方式都是重写run方法，而且run方法是没有返回结果的，
    // 也就是main方法是不知道开启的线程什么时候开始执行，什么时候结束执行，也获取不到对应的返回结果。
    // 而且run方法也不能把可能产生的异常抛出。在JDK1.5之后推出了通过实现Callable接口的方式来创建新的线程，这种方式可以获取对应的返回结果
    public static void main(String[] args) {
        // 创建一个Callable实例
        Callable test01 = new CallableTest01();
        FutureTask task = new FutureTask<>(test01);
        // 获取一个线程 肯定是要先创建一个Thread对象  futureTask本质上是Runnable接口的实现
        Thread t1 = new Thread(task);

        t1.start();// 本质还是执行的 Runnable中的run方法，只是 run方法调用了call方法罢了
        // 获取返回的结果
        try {
            // 获取开启的线程执行完成后返回的结果
            System.out.println("线程的返回值：" + task.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        callable2();
        System.out.println("main方法end ....");

        //实现Runnable接口和实现Callable接口的区别:
        //
        //1. Runnable是自从java1.1就有了，而Callable是1.5之后才加上去的
        //2. Callable规定的方法是call(),Runnable规定的方法是run()
        //3. Callable的任务执行后可返回值，而Runnable的任务是不能返回值(是void)
        //4. call方法可以抛出异常，run方法不可以
        //5. 运行Callable任务可以拿到一个Future对象，表示异步计算的结果。它提供了检查计算是否完成的方法，以等待计算的完成，
        // 并检索计算的结果。通过Future对象可以了解任务执行情况，可取消任务的执行，还可获取执行结果。
        //6. 加入线程池运行，Runnable使用ExecutorService的execute方法，Callable使用submit方法。
        //
        //其实Callable接口底层的实现就是对Runable接口实现的封装，线程启动执行的也是Runable接口实现中的run方法，
        // 只是在run方法中有调用call方法罢了
    }

    private static void callable2() {
        Callable test02 = new CallableTest02();
        FutureTask task2 = new FutureTask<>(test02);
        Thread t2 = new Thread(task2);
        t2.start();
        String str = null;
        try {
            str = String.valueOf(task2.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        String[] s1 = str.split("/");
        System.out.println("线程" + s1[0] + "的返回值：" + s1[1]);
    }
}

class CallableTest01 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("我是"+Thread.currentThread().getName());
        int sum = 0 ;
        for (int i = 0; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
}

class CallableTest02 implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("我是"+Thread.currentThread().getName());
        int sum = 0 ;
        for (int i = 0; i <= 100; i++) {
            sum += i;
        }
        return Thread.currentThread().getName() + "/" + sum;
    }
}
